using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Text.Tagging;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Utilities;
using PostscriptTools.Classifier;

namespace PostscriptTools.Intellisense {

	[Export(typeof(IQuickInfoSourceProvider))]
	[ContentType("postscript")]
	[Name("Postscript Quick Operator Info")]
	[Order(Before = "default")]
	internal class PostscriptTokenQuickInfoSourceProvider : IQuickInfoSourceProvider {
		[Import]
		internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }

		[Import]
		internal ITextBufferFactoryService TextBufferFactoryService { get; set; }
		public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) {
			return new PostscriptTokenQuickInfoSource(this, textBuffer);
		}

	}

	/// <summary>
	/// Provide QuickInfo for postscript standard operators
	/// </summary>
	class PostscriptTokenQuickInfoSource : IQuickInfoSource {
		private readonly ITextBuffer _buffer;
		private readonly PostscriptTokenQuickInfoSourceProvider _provider;
		public PostscriptTokenQuickInfoSource(PostscriptTokenQuickInfoSourceProvider provider, ITextBuffer subjectBuffer) {
			_provider = provider;
			_buffer = subjectBuffer;
		}

		public void Dispose() {
		}

		public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> quickInfoContent, out ITrackingSpan applicableToSpan) {
			// Map the trigger point down to our buffer.
			applicableToSpan = null;
			if (LineProgress.PredefinedPostscriptNames == null) {
				return;
			}
			SnapshotPoint? subjectTriggerPoint = session.GetTriggerPoint(_buffer.CurrentSnapshot);
			if (!subjectTriggerPoint.HasValue) {
				return;
			}
			ITextSnapshot currentSnapshot = subjectTriggerPoint.Value.Snapshot;
			var querySpan = new SnapshotSpan(subjectTriggerPoint.Value, 0);

			//look for occurrences of our QuickInfo words in the span
			ITextStructureNavigator navigator = _provider.NavigatorService.GetTextStructureNavigator(_buffer);
			TextExtent extent = navigator.GetExtentOfWord(subjectTriggerPoint.Value);
			string searchText = extent.Span.GetText();

			foreach (KeyValuePair<string, string> pair in LineProgress.PredefinedPostscriptNames) {
				int foundIndex = pair.Key.IndexOf(searchText, StringComparison.Ordinal);
				if (foundIndex == 0) {
					applicableToSpan = currentSnapshot.CreateTrackingSpan(extent.Span.Start.Position, searchText.Length, SpanTrackingMode.EdgeInclusive);
					quickInfoContent.Add(pair.Value ?? "");
				}
			}
			return;
		}
	}
}

